﻿//-----------------------------------------------------------------------
// <copyright file="WordProcessorBase.cs" company="Anurag Chatterjee">
//     Copyright (c) Anurag Chatterjee. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace WordsBase
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    /// <summary>
    /// The word processor base class
    /// </summary>
    public class WordProcessorBase : FileSourceProcessorBase, IWordProcessor
    {
        /// <summary>
        /// Gets or sets the words list.
        /// </summary>
        /// <value>
        /// The words list.
        /// </value>
        protected Dictionary<string, string> WordsList
        {
            get; set;            
        }

        /// <summary>
        /// Adds the word to derived list.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="word">The word.</param>
        /// <returns>
        /// Whether the operation was a success
        /// </returns>
        public bool AddWordToDerivedList(string root, string word)
        {
            if (string.IsNullOrWhiteSpace(root))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, root);
                return false;
            }

            if (string.IsNullOrWhiteSpace(word))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, word);
                return false;
            }

            if (null == this.AddWordToRootInSource)
            {
                this.LastErrorMessage = Messages.SystemError;
                return false;
            }

                var result = this.AddWordToRootInSource(root, word);
                if (result)
                {
                ////if this is the first word being added to the collection
                    if (null == this.WordsList)
                    {
                       this.WordsList = new Dictionary<string, string>();
                    }

                    if (this.WordsList.ContainsKey(word))
                    {
                        this.LastErrorMessage = string.Format(Messages.CannotAddSameWord, word);
                        return false;
                    }

                    this.WordsList.Add(word, root);
                    return true;
                }
            
            return false;
        }

        /// <summary>
        /// Deletes the word from derived list.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="word">The word.</param>
        /// <returns>
        /// Whether the operation was a success
        /// </returns>
        public bool DeleteWordFromDerivedList(string root, string word)
        {
            if (string.IsNullOrWhiteSpace(root))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, root);
                return false;
            }

            if (string.IsNullOrWhiteSpace(word))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, word);
                return false;
            }

            if (null == this.DeleteWordFromRootInSource)
            {
                this.LastErrorMessage = Messages.SystemError;
                return false;
            }

            var result = this.DeleteWordFromRootInSource(root, word);
            if (result)
            {
                if (null == this.WordsList)
                {
                    this.LastErrorMessage = Messages.SystemError;
                    return false;
                }

                if (!this.WordsList.ContainsKey(word))
                {
                    this.LastErrorMessage = string.Format(Messages.WordNotPresent, word);
                    return false;
                }

                string existingRoot = this.WordsList[word];
                if (string.Compare(existingRoot, root, false, CultureInfo.CurrentCulture) != 0)
                {
                    this.LastErrorMessage = Messages.RootNotPresent;
                    return false;
                }

                this.WordsList.Remove(word);
                return true;
            }

            return false;
        }

        /// <summary>
        /// Gets all words with root.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <returns>
        /// All words with this root
        /// </returns>
        public List<string> GetAllWordsWithRoot(string root)
        {
            if (string.IsNullOrWhiteSpace(root))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, root);
                return new List<string>();
            }

            if (null == this.WordsList)
            {
                this.LastErrorMessage = Messages.SystemError;
                return new List<string>();
            }

            var wordsWithSameRoot = new List<string>();
            foreach (var keyValuePair in this.WordsList)
            {
                if (string.Compare(keyValuePair.Value, root, false, CultureInfo.CurrentCulture) == 0)
                {
                    wordsWithSameRoot.Add(keyValuePair.Key);
                }
            }

            return wordsWithSameRoot;
        }

        /// <summary>
        /// Gets the word root.
        /// </summary>
        /// <param name="word">The word.</param>
        /// <returns>
        /// The root of the word
        /// </returns>
        public KeyValuePair<string, string> GetWordRoot(string word)
        {
            if (string.IsNullOrWhiteSpace(word))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, word);
                return new KeyValuePair<string, string>();
            }

            if (null == this.WordsList)
            {
                this.LastErrorMessage = Messages.SystemError;
                return new KeyValuePair<string, string>();
            }

            if (!this.WordsList.ContainsKey(word))
            {
                this.LastErrorMessage = string.Format(Messages.WordNotPresent, word);
                return new KeyValuePair<string, string>(string.Empty, word);
            }

            return new KeyValuePair<string, string>(this.WordsList[word], word);
        }

        /// <summary>
        /// Updates the word in derived list.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="oldWord">The old word.</param>
        /// <param name="updatedWord">The updated word.</param>
        /// <returns>
        /// Whether the operation was a success
        /// </returns>
        public bool UpdateWordInDerivedList(string root, string oldWord, string updatedWord)
        {
            if (string.IsNullOrWhiteSpace(root))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, root);
                return false;
            }

            if (string.IsNullOrWhiteSpace(oldWord))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, oldWord);
                return false;
            }

            if (string.IsNullOrWhiteSpace(updatedWord))
            {
                this.LastErrorMessage = string.Format(Messages.EmptyArgument, updatedWord);
                return false;
            }

            if (null == this.UpdateWordInRootInSource)
            {
                this.LastErrorMessage = Messages.SystemError;
                return false;
            }

            var result = this.UpdateWordInRootInSource(root, oldWord, updatedWord);
            if (result)
            {
                if (null == this.WordsList)
                {
                    this.LastErrorMessage = Messages.SystemError;
                    return false;
                }

                if (!this.WordsList.ContainsKey(oldWord))
                {
                    this.LastErrorMessage = string.Format(Messages.WordNotPresent, oldWord);
                    return false;
                }

                string existingRoot = this.WordsList[oldWord];
                if (string.Compare(existingRoot, root, false, CultureInfo.CurrentCulture) != 0)
                {
                    this.LastErrorMessage = Messages.RootNotPresent;
                    return false;
                }

                if (this.WordsList.ContainsKey(updatedWord))
                {
                    this.LastErrorMessage = string.Format(Messages.CannotAddSameWord, updatedWord);
                    return false;
                }

                ////update the word in the dictionary
                this.WordsList.Remove(oldWord);
                this.WordsList.Add(updatedWord, root);
                return true;
            }

            return false;
        }

        /// <summary>
        /// Gets the last error message.
        /// </summary>
        /// <returns>
        /// The last error message
        /// </returns>
        public string GetLastErrorMessage()
        {
            return this.LastErrorMessage;
        }
    }
}
